home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
utils
/
stlogin4.lzh
/
GETTY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-10
|
11KB
|
385 lines
/* UNIX like GETTY program. Kees Lemmens; Aug '92
This program provides a way to start a shell on a remote line
such as a modem.
It can be run on an ATARI without MINT multitasking kernel, but
only with MINT you'll be able to run on the background !
If you're not using MINT you also have to recompile with new pathnames
for "wtmp", "passwd", other signal handling (predefined in this source)
and with an empty "devpath" .
Features:
- Can handle (Hayes) modem lines as well as hardwired terminals.
- Redirects in and output to any line (or pipe) specified in <tty>.
- Searches the username in the passwordfile and determines from
there the SHELL and the (encrypted) PWD.
- Suppresses echo while entering the password.
- If the user is found and the password is alright it starts the program
defined in SHELL. It restores the login prompt after the shell has
finished on a direct line, a modemline receives a hangup.
- Writes a log entry in (UNIX-like) UTMP and WTMP files to see who logged
in where and when. WTMP logging is only used if there's is already an
existing (empty ?) WTMP file.
The same applies for a BTMP file, where bad logins will be logged.
UTMP will be created if it does not exist.
- Puts the username and home directory in the environment as variables
LOGNAME and HOME. Also TTYNAME and an initial PATH variable is set.
- The getty program aborts when a modemline does not respond with "OK"
when the program sends an initial reset to the modem (ATZ).
- Can also be run in background mode with the -d option (only MINT !)
- Number of rings before answering the modemline can be adjusted by
the -r option. (default after 1 ring)
Known Bugs:
- The baudrate can only be set for the current serial line, i.e. the
AUX: line. This implies that you have to set the RS232 parameters
manually for other getty lines. This is because the ATARI Rsconf()
routine only works for the current line.
It seems however that this is improved since MINT version 1.08.
- The UTMP and WTMP entries are only partly filled in.
Take care: WTMP and BTMP are never truncated, so they grow without bounds.
- The program checks for the presence of MINT. It can also run under
normal TOS, but it can only do the most basical things then !
In this case it can only work with the AUX: line; shells and the
passwd file must be on drive c: (passwd in /etc)
In your own password file it is important to have passwords with the
right encryption in your entries, or else you won't be able to login !
Here I used a (simple) algorithm like EOR with 19+positionnr. , but
you're free of course to choose your own !
Version 1.1 : Stderr redirection fixed
(Oct 92) Pid logged in wtmp
Shell now forks in stead of running as subprocess
Can also run in background mode without using bg.ttp
1.2 : UTMP logging build in.
1.3 : Can be used on normal TOS now.
1.4 : - SHELL and HOME dir in passwd file can be both in UNIX
and in TOS notation now.
- Textfile /etc/welcome will be printed if available
instead of build in welcome message.
- Program prints error message now if shell entry
in passwd could not be started.
1.5 : - Getty pid logged in /etc/syslog.
- Slightly adjusted delay times for modem routines.
- PURE_C delay function replaced by Delay (modem.c).
1.6 : - Multiuser behaviour improved by setting the user and
group id's before starting a shell.
- From now on getty can only be run by uid 0 (root).
- Modem is reset when getty terminates.
- Extra option (-i) to supply modem init commands from
the commandline.
Any questions or suggestions about this program can be send to:
lemmens@dv.twi.tudelft.nl
*/
#ifdef __PUREC__
#include <tos.h>
#else
#include <osbind.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include "ux_misc.h"
#include "modem.h"
/* UNIX headers */
#include <utmp.h>
#include <pwd.h>
#include <signal.h>
#include <ioctl.h> /* ioctl and TIOC */
int hwfl,fp,mintflag;
char *errlog;
static struct utmp w;
#define MAX_FAIL 4
void sleep(unsigned s);
void LogMsg(char *txt)
{ FILE *log;
int x;
time_t tm;
time(&tm);
for(x=0;x<10 && (log=fopen(errlog,"a")) == NULL;x++)
sleep(1); /* could be opened by another application */
if(log==NULL) log=stderr;
fprintf(log,"GETTY (%03d) %.24s: %s\n",Pgetpid(),ctime(&tm),txt);
if(log != stderr) fclose(log);
}
void fatal(char *txt)
{ LogMsg(txt);
exit(1);
}
void Term_Handler()
{ if(! hwfl) mod_reset();
fatal("Terminate signal received.");
}
void log_utmp(struct utmp *w)
{ setutent();
pututline(w);
endutent();
}
void log_xtmp(struct utmp *w,char *file)
{ utmpname(file);
setutent();
lseek(utmp_fd,0,SEEK_END); /* goto end of file */
pututline(w);
endutent();
utmpname(UTMP_FILE);
}
void start_shell(struct passwd *pwent)
{ char shell[100];
FILE *welcome;
static char environ[500];
static char *Badshell ="Problem starting shell !!\r\n";
static char *WelcomeTxt ="\r\n\nWelcome on ATARI\r\n";
sprintf(shell,"%c:%.97s",mintflag ? 'u' : 'c',
ux2dos(pwent->pw_shell));
sprintf(environ,"LOGNAME=%s%cHOME=u:%s%cPATH=%s%cTTYNAME=%s",
pwent->pw_name,0,ux2dos(pwent->pw_dir),0,PATH,0,w.ut_line);
strncpy(w.ut_user,pwent->pw_name,sizeof(w.ut_user));
Fforce(-1,fp); /* redirect terminal to line (Pexec) */
if((welcome = fopen(WELCOME,"r")) != NULL)
{ while(fgets(WelcomeTxt,99,welcome) != NULL)
Put(WelcomeTxt);
fclose(welcome);
}
else
Put(WelcomeTxt);
#ifndef DEBUG
if(mintflag)
{ if((w.ut_pid =(int)Pfork()) == 0)
{ /* must change uid & gid in a subprocess or it will
be impossible to change back to uid 0 again !
*/
(void)Psetuid(pwent->pw_uid);
(void)Psetgid(pwent->pw_gid);
w.ut_pid=Pexec(200,shell," ",environ);
Put(Badshell); /* only reach this if Pexec overlay fails */
exit(0);
}
}
w.ut_type=USER_PROCESS;
log_utmp(&w);
log_xtmp(&w,WTMP_FILE);
if(mintflag)
Pwait3(0,(long *)0); /* wait for shell to exit */
else if((w.ut_pid=(int)Pexec(0,shell," ",environ)) < 0)
Put(Badshell);
#endif
w.ut_type = DEAD_PROCESS;
log_xtmp(&w,WTMP_FILE);
Fforce(-1,0);
}
void set_baudrate(int baud)
{ struct sgttyb sg;
struct { char flag; int rate; }
t[] = { 0, 0, 7, 300, 8, 600, 9, 1200,
11, 2400, 12, 4800, 13, 9600, 14, 19200
};
int nr,max=(int)(sizeof(t)/sizeof(t[0]));
for(nr=0;baud != t[nr].rate; nr++)
if(nr>=max)
fatal("Unsupported baudrate !");
ioctl(0, TIOCGETP, &sg);
sg.sg_ispeed = sg.sg_ospeed = t[nr].flag;
ioctl(0, TIOCSETP, &sg);
/* With the current driver this can only set AUX: port ! */
}
int init_modem(int baud,char *cmd)
{ set_baudrate(baud);
mod_puts(cmd);
return mod_wait("OK",20,0);
}
void daemon_mode(void)
{
/* if we are the child, kill parent to become a daemon */
/* proc grp is changed to avoid signal problems (SIGCHLD) */
if(Pfork()) Pwait(); /* wait to be killed !! (gna gna) */
(void)Psetpgrp(0,0);
(void)Pkill(Pgetppid(),SIGKILL);
}
void handle_login(void)
{ int cnt;
struct passwd *pwent;
char name[50],pwd[50];
char *lg_txt="\r\nLogin : ";
char *pw_txt="\r\nPassword: ";
char *er_txt=" Invalid";
for(cnt=0;cnt<MAX_FAIL;cnt++)
{ do
{ Put(lg_txt);
while(Cconis()==0)
sleep(1); /* only to avoid heavy system load */
Get(name,40,1);
}while(strlen(name)==0);
Put(pw_txt);
Get(pwd,40,0);
if((pwent=getpwnam(name)) != NULL)
if(check_pw(pwd,pwent) >= 0) /* succesfull login */
{ (void)Pnice(-20); /* restore normal priority */
fflush(stdin);
start_shell(pwent);
return; /* force hangup after logout */
}
Put(er_txt);
strncpy(w.ut_name,name,sizeof(w.ut_name));
w.ut_type=DEAD_PROCESS;
log_xtmp(&w,BTMP_FILE);
}
}
void usage(void)
{ fputs(